package com.parkinginfo.manager;


/*
 * Author: Deepika Gohil
 * 
 * This activity will be used to display parking around you or
 * at specific places.
 */

import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.http.Header;
import org.apache.http.HeaderElement;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.entity.HttpEntityWrapper;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.shapes.RectShape;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.AsyncTask;
import android.os.Bundle;
import android.text.format.DateUtils;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageButton;
import android.widget.TextView;
import android.widget.Toast;



import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;
import com.google.android.maps.OverlayItem;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;


import com.parkinginfo.manager.R;

public class GoogleParkingActivity extends MapActivity implements LocationListener
{
	public static MapView mapView;
	
	private int fixedFlag = 0; 
	
	public static double lat;
	public static double lon;
	
	private double radius = 0.25;
	private String provider;
	protected LocationManager locationManager;
	
    private static final long MINIMUM_DISTANCE_CHANGE_FOR_UPDATES = 10; // in Meters
    private static final long MINIMUM_TIME_BETWEEN_UPDATES = 1000; // in Milliseconds
    
    private boolean noDataFound = false;
    
    /*
     * added starts here.
     */
    public static ProgressDialog pdialog;
    static String responseString = null;
    
    
    String serviceURL = "http://api.sfpark.org/sfpark/rest/availabilityservice?lat=37.792275&long=-122.397089&radius=0.25&uom=mile&response=json";
   
    private static final int SECOND_IN_MILLIS = (int) DateUtils.SECOND_IN_MILLIS;
    public static String timeStampXML = null;
    public static Date          timeStamp;
    public static int           timeStampMinutes;
   
    //public static ArrayList<GarageDetails> parkingGarages = null;
    public static MapController mc;
   
    static ItemizedOverLays ItemizedOverlayArray = null;
   
    static final double INITIAL_LATITUDE = 37.78;
    static final double INITIAL_LONGITUDE = -122.42;
    Location         userLocation;
    ProgressDialog pd = null;
    Drawable normal_drawable;
    
    
    Context father = this;
	/*
	 * added ends here.
	 */
    
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState)
    
    {
    	if(getIntent().getExtras() !=null)
    	{
    		lat = (getIntent().getExtras()).getDouble("lat");
    		lon = (getIntent().getExtras()).getDouble("lon");
    		fixedFlag = 1;
    	}
    	
    	super.onCreate(savedInstanceState);	
    	locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);	
        setContentView(R.layout.showmap);
        
	    setUpButtons(); 
        
        mapView = (MapView) findViewById(R.id.mapView);
    	mapView.setBuiltInZoomControls(true);
        View zoomView = mapView.getZoomControls(); 
        
        if(fixedFlag == 0)
        		getUserLocation();
        
        this.resetandRefresh();
        
        mapView.displayZoomControls(true); 
	    mc = mapView.getController();
       
	    createUserMarker();
	   
	    mapView.invalidate();
    }
    
    
    private void setUpButtons()
    {
    	ImageButton increase = (ImageButton) findViewById(R.id.up);
 	    increase.setOnClickListener(new OnClickListener() {
 			
 			@Override
 			public void onClick(View v) 
 			{
 				if(radius < 1)
 				{
 					radius = radius + 0.05;
 					radius = Double.parseDouble(new DecimalFormat("#.##").format(radius));
 					TextView radiusText = (TextView)findViewById(R.id.radius_string);
 					String result = "Current Radius: " + radius + " miles";
 					
 					radiusText.setText(result);
 				}
 			};
 		});
         
         ImageButton decrease = (ImageButton) findViewById(R.id.down);
         decrease.setOnClickListener(new OnClickListener() {
 			
 			@Override
 			public void onClick(View v)
 			{
 				if(radius > 0.05)
 				{
 					radius = radius - 0.05;
 					radius = Double.parseDouble(new DecimalFormat("#.##").format(radius));
 					TextView radiusText = (TextView)findViewById(R.id.radius_string);
 					String result = "Current Radius: " + radius + " miles";
 					
 					radiusText.setText(result);
 				}
 			};
 		});
         
         ImageButton refresh = (ImageButton) findViewById(R.id.refresh);
         refresh.setOnClickListener(new OnClickListener() 
         {
 			@Override
 			public void onClick(View v) 
 			{
 			    if(fixedFlag == 0)
 		        		getUserLocation();
 		        
 		        resetandRefresh();
 		        
 		        mapView.displayZoomControls(true); 
 			    mc = mapView.getController();
 		       
 			    createUserMarker();
 			   
 			    mapView.invalidate();
 			};
 		});
 	    
 	    ImageButton bsearch = (ImageButton) findViewById(R.id.go_search_mapview);
         bsearch.setOnClickListener(new OnClickListener() {
 			
 			@Override
 			public void onClick(View v) 
 			{
 				Intent it = new Intent(getApplicationContext(),GoogleParkingActivity.class);
 				father.startActivity(it);
 			};
 		});
         
         ImageButton goto_list = (ImageButton) findViewById(R.id.go_listview);
         goto_list.setOnClickListener(new OnClickListener() {
 			
 			@Override
 			public void onClick(View v) 
 			{
 				Intent it = new Intent(getApplicationContext(),ListViewer.class);
 				father.startActivity(it);
 			};
 		});
    }
    
    private void getUserLocation()
	{
		//start GPS for updates
    	locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,MINIMUM_TIME_BETWEEN_UPDATES, 
        		MINIMUM_DISTANCE_CHANGE_FOR_UPDATES, this);
    	
    	Location location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
    	if(location != null)
    	{
    		lat = location.getLatitude();
    		lon = location.getLongitude();
    		String toastText = "Lat: " +lat+", Lon: "+lon;
    		Toast.makeText(GoogleParkingActivity.this, toastText, Toast.LENGTH_SHORT).show();
    		
    		String latlon = "@ "+lat +" , " + lon + "+/- 200m";
    	}
    	else
    	{
    		String latlon = "";
    		Toast.makeText(GoogleParkingActivity.this, "Can not find location", Toast.LENGTH_SHORT).show();
    	}
	}
    
    void resetandRefresh()
    {
    	reset();
    	refresh();
    }
    
    
    /*
     * Reset everything
     */
    void reset() {
        List<Overlay> mapOverlays = mapView.getOverlays();
        mapOverlays.clear();
        GoogleParkingActivity.responseString = null;
        ItemizedOverlayArray = null;
        if (((ParkingManagerApplication)getApplication()).parkingGarages != null) {
        	((ParkingManagerApplication)getApplication()).parkingGarages.clear();
        }
        ((ParkingManagerApplication)getApplication()).parkingGarages = null;
    }
        
    void refresh() {
        pdialog = new ProgressDialog(mapView.getContext());
        LoadDataTask ld = new LoadDataTask();
        ld.execute("String");
    }
    
    /*
     * create marker for user
     */
	 private void createUserMarker() 
	    {
		   GeoPoint p = getPoint(lat, lon);
	       // mc.setCenter(p);
	        mc.animateTo(p);
	        int zoomlevel = mapView.getMaxZoomLevel(); 
	        mc.setZoom(zoomlevel - 3);
		    mapView.setSatellite(false);
		 
		 List<Overlay> mapOverlays = mapView.getOverlays();
		 Drawable drawable = this.getResources().getDrawable(R.drawable.car);
		 MyOverLays itemizedoverlay = new MyOverLays(drawable, this);
		 OverlayItem overlayitem = new OverlayItem(p, "You!:", "You are here!");
		 itemizedoverlay.addOverlay(overlayitem);
		 mapOverlays.add(itemizedoverlay);
		}
    
    /*
     * General Methods
     */
    public static Location getLocation(GeoPoint p) {
        Location result = new Location("");
        result.setLatitude(p.getLatitudeE6() / 1.0E6);
        result.setLongitude(p.getLongitudeE6() / 1.0E6);
        return result;
    }

    /*
     * General Methods
     */
    public static GeoPoint getPointFromLocation(Location location) {
        return getPoint(location.getLatitude(),
                        location.getLongitude());
    }

    /*
     * General Methods
     */
    public static GeoPoint getPoint(double lat, double lon) {
        return new GeoPoint((int) (lat * 1E6),
                            (int) (lon * 1E6));
    }
	
	@Override
	protected boolean isRouteDisplayed() {
		return false;
	}
	 
	
	
	@Override
	protected void onResume() {
		super.onResume();
		//if toggle switch is on, get the latest updates on resume and show filtered tasks
		if(fixedFlag == 0)
			getUserLocation();
		//TODO call the method to get latest parking info
	}
	
	

	@Override
	public void onLocationChanged(Location location) {
	
		if (location != null) 
		{
		// Toast about location and also reload the filtered tasks
			lat = location.getLatitude();
    		lon = location.getLongitude();
    		String toastText = "Location changed to: Lat: " +lat+", Lon: "+lon;
    		Toast.makeText(GoogleParkingActivity.this, toastText, Toast.LENGTH_SHORT).show();
    		userLocation = location;
    		//TODO call the method to get latest parking info
    		
            this.resetandRefresh();
            
            mapView.displayZoomControls(true); 
    	    mc = mapView.getController();
           
    	    createUserMarker();
    	   
    	    mapView.invalidate();
		}
	}

	@Override
	public void onProviderDisabled(String provider) {
		Toast.makeText(GoogleParkingActivity.this,"Provider Disabled",Toast.LENGTH_SHORT ).show();
	}

	@Override
	public void onProviderEnabled(String provider) {
		Toast.makeText(GoogleParkingActivity.this,"Provider Enabled",Toast.LENGTH_SHORT ).show();
	}

	@Override
	public void onStatusChanged(String provider, int status, Bundle extras) {
	}
	
	
	 
	 	/*
		 * Load Data Task: Asynchronous
		 */
		private class LoadDataTask extends AsyncTask<String, Void, Void> {
	        protected void onPreExecute() {
	            pdialog.setMessage("Downloading data..");
	            pdialog.show();
	        }

	        protected Void doInBackground(String... urls) {
	            loadData();
	        	//connect(serviceURL);
	            return null;
	        }

	        protected void onPostExecute(Void unused) {
	            try {
	                pdialog.setMessage("Reading data..");
	                readData();
	                pdialog.setMessage("Displaying data..");
	                displayData(false);
	                pdialog.dismiss();
	            } catch (JSONException e) {
	                e.printStackTrace();
	            }
	        }
	    }
	 
	    public boolean loadData() 
	    {
	    	boolean didLoad = false;
	    	/*
	        if (GoogleParkingActivity.responseString != null) {
	            return true;
	        }
	        */
	        try 
	        {
	          //GoogleParkingActivity.responseString = getStringContent(serviceURL);
	      	connect(serviceURL);      
	        } catch (Exception e) {
	            e.printStackTrace();
	        }
	        if (GoogleParkingActivity.responseString != null) {
	            didLoad = true;
	        }
	        return didLoad;
	    }
	    
	    private static class InflatingEntity extends HttpEntityWrapper {
	        public InflatingEntity(HttpEntity wrapped) {
	            super(wrapped);
	        }
	    }
	        
	    /***added ***/
	    
	    public JSONObject connect(String url)
	    {
	    	url = "http://api.sfpark.org/sfpark/rest/availabilityservice?lat="+lat+"&long="+lon+"&radius="+radius+"&uom=mile&response=json&pricing=yes";
	    	ParkingLOG(url);
	    	
	    	
	        HttpClient httpclient = new DefaultHttpClient();
	        HttpGet httpget = new HttpGet(url); 
	        HttpResponse response;
	        JSONObject json = new JSONObject();
	        try {
	            response = httpclient.execute(httpget);
	            HttpEntity entity = response.getEntity();
	            
                final Header encoding = entity.getContentEncoding();
                
                if (encoding != null) {
                    for (HeaderElement element : encoding.getElements()) {
                        if (element.getName().equalsIgnoreCase("gzip")) {
                            response.setEntity(new InflatingEntity(response.getEntity()));
                            break;
                        }
                    }
                }
                entity = response.getEntity();
	            if (entity != null) {
	                // A Simple JSON Response Read
	                InputStream instream = entity.getContent();             
	                String result= convertStreamToString(instream);
	                
	                GoogleParkingActivity.responseString = result;
	                json=new JSONObject(result);
	                instream.close();
	            }

	        } catch (ClientProtocolException e) {
	            e.printStackTrace();
	        } catch (IOException e) {
	            e.printStackTrace();
	        } catch (JSONException e) {
	            e.printStackTrace();
	        }

	        return json;
	    }
	    public static String convertStreamToString(InputStream is) {
	        BufferedReader reader = new BufferedReader(new InputStreamReader(is));
	        StringBuilder sb = new StringBuilder();

	        String line = null;
	        try {
	            while ((line = reader.readLine()) != null) {
	                sb.append(line + "\n");
	            }
	        } catch (IOException e) {
	            e.printStackTrace();
	        } finally {
	            try {
	                is.close();
	            } catch (IOException e) {
	                e.printStackTrace();
	            }
	        }
	        return sb.toString();
	    }
	    
	    
	    
	   public void readData() throws JSONException {
	           
		   System.out.println("Readin starts.");
	            if (GoogleParkingActivity.responseString == null || GoogleParkingActivity.responseString == "") {
	            	String toastText = "No respose found!";
	        		Toast.makeText(GoogleParkingActivity.this, toastText, Toast.LENGTH_SHORT).show();
	                return;
	            }
	            ParkingLOG(GoogleParkingActivity.responseString);
	            String	   message = null;
	            JSONObject rootObject = null;
	            JSONArray  jsonAVL = null;
	            String num_records = null;
	            String status = null;

	            //pdialog.setMessage("reading data....parsing starts.");
	            ParkingLOG("Parsing starts");
	            
	            try
	            {
	            rootObject = new JSONObject(GoogleParkingActivity.responseString);
	            message = rootObject.getString("MESSAGE");
	            num_records = rootObject.getString("NUM_RECORDS");
	            status = rootObject.getString("STATUS");
	            timeStampXML = rootObject.getString("AVAILABILITY_UPDATED_TIMESTAMP");    
	            jsonAVL = rootObject.getJSONArray("AVL");
	            }catch(JSONException e)
	            {
	            	noDataFound = true;
	            }
	            
	            //ParkingLOG("Message is: " + message + ",$$JSON AVALLLLDEEPIKA :" + jsonAVL + ", $$TIMESTAMPPDEEPI: "+ timeStampXML);
	            ParkingLOG("Parsing ends.");
	            
	            //pdialog.setMessage("Parsing ends.");

	            int i=0;
	            
	          if(!noDataFound)
	          {
	             
	            int len = jsonAVL.length();

	            if (((ParkingManagerApplication)getApplication()).parkingGarages == null) {
	            	((ParkingManagerApplication)getApplication()).parkingGarages = new ArrayList<GarageObject>();
	            } else {
	            	((ParkingManagerApplication)getApplication()).parkingGarages.clear();
	            }

	            /*
	             * Here I am getting all the gargade details and make JSON objects for all the garages.
	             * 
	             * annotation is the GarageDetails.....and assnotations[] is the public static array of all the Garages.
	             * you can use it in activity....If you want to parse the JSONObject for particular Garage -> Parse the 'TheGarageInformation'
	             * I am calling the parseJSONData(), whenever I update the marker on the map....so you can add your code in this function only.
	             */
	            pdialog.setMessage("Add to annotations.");
	            for(i = 0; i < len; ++i) {
	                JSONObject interestArea = jsonAVL.getJSONObject(i);
	                GarageObject park = new GarageObject(i);
	                
	                park.TheGarageInformation = interestArea;
	                park.parseJSONData();
	                
	                ((ParkingManagerApplication)getApplication()).parkingGarages.add(park);
	                ParkingLOG("JSON Object added!");
	                ParkingLOG("Title:" + park.Address + " Intersection: " + park.interSection + " Type: " + park.type 
	                		+ " Desc: "+ park.desc + " TEL: " + park.telephone
	                		+ " Used: "+ park.used_spaces + " Capacity: " + park.total_capacity + " Avail: " + park.available_spaces
	                		+ " Rates Details: " + park.ratesDetails + " Operational Hours: " + park.hoursDetails);
	            }
	          }
	            //ParkingLOG("JSON Objects added finished!");
	        }
	   
	   
	   public boolean displayData(boolean progress) {

	        if (GoogleParkingActivity.responseString == null || GoogleParkingActivity.responseString == "" || noDataFound) {
	        	String toastText = "No records Founds!";
	    		Toast.makeText(GoogleParkingActivity.this, toastText, Toast.LENGTH_SHORT).show();
	            return false;
	        }

	        if ((ItemizedOverlayArray !=null)) {
	            updateMap();
	            return true;
	        }	    
	        updateMap();
	        
	        return true;
	    }

	    public void updateMap() {
	        if (mapView == null) {
	            return;
	        }
	       
	        
	        normal_drawable = this.getResources().getDrawable(R.drawable.marker);
	        
	        /********added********/
	        ShapeDrawable invisible = new ShapeDrawable(new RectShape());
	        invisible.getPaint().setColor(0x00000000);
	        
	        ItemizedOverlayArray = new ItemizedOverLays(normal_drawable,mapView.getContext());
	          
	        
	        pd = new ProgressDialog(this);
	        pd.setCancelable(false);
	        pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
	        pd.setMessage("Calculating...");
	        pd.setProgress(0);
	        pd.setMax(ItemizedOverlayArray.size());
	        pd.show();

	        LoadOverlaysTask ld  = new LoadOverlaysTask();
	        ld.execute("String");
	    }
	    
	    
	    class LoadOverlaysTask extends AsyncTask<String, Void, Void> {
	    	List<Overlay> mapOverlays = mapView.getOverlays();
	        protected void onPreExecute() {
	            pd.show();
	        }

	        protected Void doInBackground(String... urls) {
	            
	        	for (GarageObject a: ((ParkingManagerApplication)getApplication()).parkingGarages)
	 	        {
	        		Drawable noSpace_drawable = (((ParkingManagerApplication)getApplication()).getResources().getDrawable(R.drawable.blackdot));
	     	        Drawable lowSpace_drawable = (((ParkingManagerApplication)getApplication()).getResources().getDrawable(R.drawable.reddot));
	     	        
	     	        OverlayItem item = null;
	     	       
	     	        
	     	       noSpace_drawable.setBounds(0,0,noSpace_drawable.getIntrinsicWidth(),noSpace_drawable.getIntrinsicHeight());
	     	       lowSpace_drawable.setBounds(0,0,lowSpace_drawable.getIntrinsicWidth(),lowSpace_drawable.getIntrinsicHeight());
		     	     
	        		 if(a.available_spaces == 0)
	        		 {
	        			 item = new OverlayItem(a.mid, a.Address + " , " + a.type, null);
		                 item.setMarker(noSpace_drawable);
		                 ItemizedOverlayArray.addOverlay(item);
	        		 }
	        		 else if(a.available_spaces<3)
	        		 {
	        			 item = new OverlayItem(a.mid, a.Address + " , " + a.type, null);
		                 item.setMarker(lowSpace_drawable);
		                 ItemizedOverlayArray.addOverlay(item);
	        		 }
	        		 else
	        		 
	        		 {
	        			 item = new OverlayItem(a.mid, a.Address + " , " + a.type, null);
		                 item.setMarker(normal_drawable);
		                 ItemizedOverlayArray.addOverlay(item);
	        		 }
	 	           
	                 
	                 pd.incrementProgressBy(1);
	 	        }       
	            return null;
	        }

	        protected void onPostExecute(Void unused) {
	            pd.setMessage("Populating pricing display");
	            if (ItemizedOverlayArray != null) {
	 	            mapOverlays.add(ItemizedOverlayArray);
	 	            }
	            
	            mapView.invalidate();
	            pd.dismiss();
	        }
	    }
	    
	    
	    
	    
	    public void ParkingLOG(String message) {
	        String logStr = getClass().getName() + ": " + message;
	        Log.v("CodeRunners", logStr);
	    
	    }
	    
}